//
// Created by Administrator on 2020/9/18.
//

#include <random>
#include <iostream>
#include <cstring>
#include "stun_header.h"

StunMessageHeader::StunMessageHeader()
    : msg_type_(0)
    , msg_length_(0)
    , magic_cookie_(StunMagicCookie)
{
    memset(transaction_tid_, 0x00, StunTrIdLength);
}

StunMessageHeader::StunMessageHeader(uint16_t msg_tyoe)
        : msg_type_(msg_tyoe)
        , msg_length_(0)
        , magic_cookie_(StunMagicCookie)
{
    transaction_tid_init();
}

StunMessageHeader::StunMessageHeader(const StunMessageHeader& rhs)
        : msg_type_(rhs.msg_type_)
        , msg_length_(rhs.msg_length_)
{
    memcpy(transaction_tid_, rhs.transaction_tid_, StunTrIdLength);
}

StunMessageHeader& StunMessageHeader:: operator=(const StunMessageHeader& rhs){
    msg_type_ = rhs.msg_type_;
    memcpy(transaction_tid_, rhs.transaction_tid_, StunTrIdLength);
    return *this;
}

void StunMessageHeader::set_msg_type(const uint16_t& msg_type){
    msg_type_ = msg_type;
}

uint16_t StunMessageHeader::get_msg_type() const{
    return msg_type_;
}

void StunMessageHeader::set_transaction_tid(const char* buffer, uint8_t len){
    if(len == StunTrIdLength){
        memcpy(transaction_tid_, buffer, StunTrIdLength);
    }
}

uint8_t *StunMessageHeader::get_transaction_tid() {
    return transaction_tid_;
}

bool StunMessageHeader::parse(const char* buffer, uint16_t length){
    if(length < StunHeaderLength){
        return false;
    }
    memcpy((void*)&msg_type_,buffer, 2);
    msg_type_ = ntoh16(msg_type_);

    memcpy((void*)&msg_length_,buffer+2, 2);
    msg_length_ = ntoh16(msg_length_);

    memcpy((void*)&magic_cookie_,buffer+4, 4);
    magic_cookie_ = ntoh16(magic_cookie_);

    if(magic_cookie_ != StunMagicCookie){
        return false;
    }
    for(size_t i =0; i< StunTrIdLength; i++){
        transaction_tid_[i] = buffer[8+i];
    }
    return true;
}

uint16_t StunMessageHeader::encode(char* buffer, uint16_t length){
    if(length < StunHeaderLength){
        return 0;
    }
    buffer = encode16(buffer, msg_type_);
    buffer = encode16(buffer, msg_length_);
    buffer = encode32(buffer, magic_cookie_);
    for(size_t i = 0; i < StunTrIdLength; i++){
        buffer[i] = transaction_tid_[i];
    }
    return StunHeaderLength;
}

StunMessageHeader::~StunMessageHeader(){

}

void StunMessageHeader::transaction_tid_init(){
    uint32_t *trad_id=(uint32_t*)transaction_tid_;
    for(size_t i = 0; i < 3; i++){
        trad_id[i] = (uint32_t)rand();
    }
}

char* StunMessageHeader::encode16(char* buf, uint16_t data)
{
    uint16_t ndata = ntoh16(data);
    memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(uint16_t));
    return buf + sizeof(uint16_t);
}

char* StunMessageHeader::encode32(char* buf, uint32_t data)
{
    uint32_t ndata = ntoh32(data);
    memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(uint32_t));
    return buf + sizeof(uint32_t);
}

uint16_t StunMessageHeader::get_msg_length(){
    return msg_length_;
}








